package com.hliushi.learn.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @ClassName MyInterceptor
 * @Description 自定拦截器, 拦截器是AOP的一种实现, 专门拦截对动态资源的后台请求, 即拦截对控制层的请求
 * @Author liushi
 * @Date 2021/7/8 19:10
 * @Version V1.0
 **/
public class MyInterceptor implements HandlerInterceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyInterceptor.class);


    /**
     * 该方法执行时机是, 当某个url已经配到了对应的Controller中的某个方法,
     * 且在这个方法执行之前, 所以preHandle(..)方法可以决定是否将请求放行,
     * 这是通过返回值来决定的, 返回true则放行, 返回false则不会向后执行
     *
     * @param request
     * @param response
     * @param handler
     * @return true才会继续执行, 返回false则取消当前请求
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // if (!(handler instanceof HandlerMethod)) {
        //     return true;
        // }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        String methodName = method.getName();
        LOGGER.info("==== 拦截到了方法: {}, 在该方法执行之前 ====", methodName);

        return true;
    }


    /**
     * 该方法的执行时机是, 当某个url已经匹配到了对应的Controller中的某个方法, 且在执行完了该方法
     * 但是在DispatcherServlet视图渲染之前, 所以在这个方法有个ModelAndView参数, 可以在此做一些修改动作
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        // if (!(handler instanceof HandlerMethod)) {
        //     return;
        // }
        LOGGER.info("执行完方法之后进执行(Controller方法调用之后), 但是此时还没进行视图渲染");
    }


    /**
     * 该方法是整个请求处理完成后(包括视图渲染)执行, 这时做一些资源的清理工作
     * 这个方法只有在preHandle(...)被成功执行后并且返回true才会被执行
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                Exception ex) throws Exception {
        // if (!(handler instanceof HandlerMethod)) {
        //     return;
        // }
        LOGGER.info("整个请求都处理完咯, DispatcherServlet也渲染了对应的视图咯, 此时我们可以一些清理的工作了");
    }
}
